Release 10.1A: OpenEdge Getting Started:
Object-oriented Programming


Defining the class constructor

The constructor of a class is a special method that gets called when a class is instantiated using the NEW statement. The constructor for a class has the same name as the class name. Unlike ordinary methods, the constructor is identified by the CONSTRUCTOR keyword. In addition, constructors cannot have a return type.

A class is not required to define a constructor. A default constructor with no parameters is provided by Progress. This default constructor is only provided when the class has not explicitly defined a constructor for the class.

In a class, it is the constructor that executes when the class is instantiated. Remember that the main block of a class is not allowed to have any executable statements. This restriction assures that all initialization of the class is done inside its constructor. The presence of the constructor as an explicitly-defined, special-purpose method allows you to take advantage of instantiation mechanisms, such as invoking the chain of constructors in a class hierarchy when the class is instantiated.

The access modifier for the constructor can be PUBLIC or PROTECTED. In order for a class to be instantiated using the NEW statement, the class must support either an explicit PUBLIC constructor or use the default constructor. When a class or procedure creates an instance of a class with the NEW statement, it is effectively telling Progress to run the other class's constructor. (For more information, see "Creating a class instance using the NEW statement" section)

If a class's constructor is not PUBLIC, it cannot be referenced in a NEW statement, because the class has not defined itself as being publicly accessible. You might want to define a PROTECTED constructor if the class can only be created as part of an object hierarchy. (For an example of a PROTECTED constructor, see the "Constructing an object" section.) When you define a class’s constructor as PROTECTED, that class cannot be directly instantiated by another class. It can only be instantiated by one of its subclasses that has a PUBLIC constructor. A PROTECTED constructor is appropriate where a class defines standard behavior to be inherited by one or more other classes, but where the super class, by itself, does not provide a complete class definition.

If you choose to define a constructor, you can define only one constructor for a class.

A constructor for a class can have zero or more parameters. The NEW statement that instantiates the class must provide the correct number and type of parameters identified in the constructor. The parameters can be used to initialize the class instance in a way that affects the behavior of its methods when they are later invoked using an object reference. Remember that a class must explicitly define a constructor if it is to take any parameters or if it inherits from a super class whose constructor takes parameters.

You never explicitly invoke a constructor from outside the class hierarchy. It is invoked implicitly when you instantiate a class, or explicitly from other constructors in the class hierarchy (using the SUPER statement). It is illegal to explicitly invoke a constructor from any method other than from a subclass's constructor.

The RETURN ERROR statement is not supported for methods, including constructors. If the constructor fails to initialize the object properly it cannot execute the RETURN ERROR statement to raise the error condition in the caller. Instead it needs to return this failure status to the caller through an output parameter. For more information on error handling, see the "Raising and handling error conditions" section.

However, if a class instantiation fails because Progress cannot create the object for any reason, Progress raises an error on the NEW statement. The conditions that raise this error include:

This is the syntax for defining a class constructor:

Syntax
CONSTRUCTOR { PUBLIC | PROTECTED } class-name  
    ( [ parameter [ , parameter ] ... ] ):  
    constructor-body 
END [ CONSTRUCTOR ] . 

Element descriptions for this syntax diagram follow:

class-name

The name of the class stripped of any relative path information. This is the class-name portion of the type-name used in the CLASS statement.

[ parameter [ , parameter ] ... ]

Any parameters that you define for the constructor. For more information on the syntax of parameter, see the “Parameter definition syntax” reference entry in OpenEdge Development: Progress 4GL Reference .

constructor-body

The logic of the constructor can be composed of any statements currently allowed within a PROCEDURE block along with new syntax permitted in methods. The constructor logic is normally used to initialize the data members of the class.

If the constructor is for a subclass, the first executable statement in the constructor must be a call to the constructor of the super class if the super class's constructor takes parameters. If the super class constructor does not take parameters, an explicit call from the subclass is optional. If you do not explicitly invoke the super class constructor, Progress automatically invokes the super class's constructor before executing the statements in the subclass constructor. For more information on how Progress handles super class and subclass constructors in a class hierarchy, see the "Constructing an object" section.

Adding a constructor to the sample class definition results in the following code:

CLASS acme.myObjs.CustObj INHERITS acme.myObjs.Common.CommonObj:  
    DEFINE PUBLIC VARIABLE iNumCusts AS INTEGER NO-UNDO. 
    DEFINE PROTECTED TEMP-TABLE ttCust NO-UNDO 
        FIELD CustNum LIKE Customer.CustNum 
        FIELD Name LIKE Customer.Name. 
    DEFINE PRIVATE VARIABLE rError  
        AS CLASS acme.myObjs.Common.ErrorObj NO-UNDO. 
    CONSTRUCTOR PUBLIC CustObj( ): 
        iNumCusts = 0. 
        /* Fill temp table and get row count */ 
        FOR EACH Customer: 
            CREATE ttCust. 
            ASSIGN 
                ttCust.CustNum = Customer.CustNum 
                ttCust.Name = Customer.Name 
                iNumCusts = iNumCusts + 1. 
        END. 
    END CONSTRUCTOR. 
    METHOD PUBLIC CHARACTER GetCustomerName(INPUT piCustNum AS INTEGER): 
        FIND ttCust WHERE ttCust.CustNum = piCustNum NO-ERROR. 
        IF AVAILABLE ttCust THEN 
            RETURN ttCust.CustName. 
        ELSE 
            RETURN ?. 
    END METHOD. 
END CLASS. 

Comparison with procedure-based programming

The constructor for a class is similar to the main block of a persistent procedure. Parameters passed to a class's constructor are similar to parameters passed to a persistent procedure when it is run. When you instantiate a class using the NEW statement, the constructor executes as part of the class constructor hierarchy and returns to the caller assigning the object reference to the instantiated class. The caller can then use this object reference to access public data members and call public methods on this class-based object. When a procedure is first run PERSISTENT, the code in its main block executes and returns to the caller, setting the procedure object handle. The caller can then access any variables that it shares globally with the procedure-based object and can use the procedure object handle to run internal procedures and user-defined functions in the procedure-based object.


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095